package math.vectorSpace.R3;

import java.awt.Graphics2D;
import math.vectorSpace.R3.visualization.RenderOrthographic;
import math.vectorSpace.R3.visualization.Visualizable;
import math.vectorSpace.R3.visualization.Render3D;
import math.vectorSpace.R3.visualization.VisualizationProperties;

public class Rectangle3D implements Visualizable {

    private Point3D origin;

    private double l, w, h;

    private Segment3D[] prismSegments = new Segment3D[12];

    /**
     * Constructs and initialises a 3D rectangular prism at the given origin 
     * with the given length, width, and height.
     * 
     * @param origin a Point3D representing the origin of the rectangular prism
     * @param l the length of the rectangular prism
     * @param w the width of the rectangular prism
     * @param h the height of the rectangular prism
     */
    public Rectangle3D(Point3D origin, double l, double w, double h) {
        this.origin = origin;
        this.l = l;
        this.w = w;
        this.h = h;

        // The bottom square
        prismSegments[0] = new Segment3D(0, 0, 0, l, 0, 0).shift(origin);
        prismSegments[1] = new Segment3D(0, 0, 0, 0, w, 0).shift(origin);
        prismSegments[2] = new Segment3D(l, 0, 0, l, w, 0).shift(origin);
        prismSegments[3] = new Segment3D(0, w, 0, l, w, 0).shift(origin);

        // The top square
        prismSegments[4] = new Segment3D(0, 0, h, l, 0, h).shift(origin);
        prismSegments[5] = new Segment3D(0, 0, h, 0, w, h).shift(origin);
        prismSegments[6] = new Segment3D(l, 0, h, l, w, h).shift(origin);
        prismSegments[7] = new Segment3D(0, w, h, l, w, h).shift(origin);

        // The four pillars
        prismSegments[8] = new Segment3D(0, 0, 0, 0, 0, h).shift(origin);
        prismSegments[9] = new Segment3D(l, 0, 0, l, 0, h).shift(origin);
        prismSegments[10] = new Segment3D(0, w, 0, 0, w, h).shift(origin);
        prismSegments[11] = new Segment3D(l, w, 0, l, w, h).shift(origin);
    }

    public Rectangle3D(Point3D origin, Point3D end) {
        this(origin, end.getX(), end.getY(), end.getZ());
    }

    /**
     * Constructs and initialises a 3D rectangular prism having a centre at the origin
     * (0,0,0) with the given length, width, and height.
     * 
     * @param l the length of the rectangular prism
     * @param w the width of the rectangular prism
     * @param h the height of the rectangular prism
     */
    public Rectangle3D(double l, double w, double h) {
        this(new Point3D(-l / 2.0, -w / 2.0, -h / 2.0), l, w, h);
    }

    public Point3D getOrigin() {
        return origin;
    }

    public double getL() {
        return l;
    }

    public double getW() {
        return w;
    }

    public double getH() {
        return h;
    }

    public Segment3D[] getSegments() {
        return prismSegments;
    }

    public void setOrigin(Point3D newOrigin) {
        Vector3D vector = new Vector3D(this.origin, newOrigin);
        this.origin = newOrigin;
        this.shift(vector);
    }

    /**
     * Shift the entire rectangular prism by the components of the
     * given vector
     * @param vector a Vector3D specifying the change in x, y, z of 
     * the rectangular prism.
     */
    public void shift(Vector3D vector) {
        for (int i = 0; i < prismSegments.length; i++) {
            prismSegments[i].shift(vector);
        }
    }

    public void shift(Point3D point) {
        for (int i = 0; i < prismSegments.length; i++) {
            prismSegments[i].shift(point);
        }
    }

    /**
     * Returns the volume of the rectangular prism
     * @return the volume of this rectangular prism
     */
    public double volume() {
        return (l * w * h);
    }

    /**
     * 
     * @param render
     * @param graphics 
     */
    @Override
    public void draw(Render3D render, Graphics2D graphics,
            VisualizationProperties properties) {
        Segment3D[] segmentList = this.getSegments();
        for (int i = 0; i < segmentList.length; i++) {
            segmentList[i].draw(render, graphics, properties);
        }
    }
}
